﻿using blacksoft.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Transactions;
using blacksoft.Constantes;
using System.Security.Cryptography;
using System.Text;
namespace blacksoft.Controllers
{
    public class INT_ReservaController : Controller
    {


        private inf245travelbusEntities db = new inf245travelbusEntities();
        //
        // GET: /INT_Reserva/

 

        public JsonResult AnularReserva(int IdReserva) {
            try 
        	{	        
                var reserva = db.Reserva.ToList().Where(c => c.IDReserva == IdReserva);
                if (reserva.Any()) {
                    var item = reserva.First();
                    item.Estado = "AN"; // Modificamos la reserva como anulado
                    db.SaveChanges();
                    return Json(new { status = 1, message = "Se anulo la reserva satisfactoriamente" });
                }
                return Json(new { status = 0, message = "No se encontro una reserva para anularla" });
	        }
	        catch (Exception ex)
	        {
                return Json(new { status = 0, message = ex.Message.ToString() });
	        }
        }

        public ActionResult ConsultaReserva() {
            int CodigoPersonaCliente = Convert.ToInt32(Session[blacksoft.Constantes.SystemField.SESION_CODIGO_PERSONA]);
            var model = new HistorialViajeDataModel();
            var historial = (from r in db.Reserva.ToList()
                             join p in db.Pasaje.ToList() on r.IDReserva equals p.IDReserva
                             join a in db.ProgramacionViaje.ToList() on p.IDProgramacionViaje equals a.IDProgramacionViaje
                             join rp in db.Ruta_x_UnidadTransporte.ToList() on a.IdRuta_x_UnidadTransporte equals rp.IdRuta_x_UnidadTransporte
                             join x in db.Ruta.ToList() on rp.IDRuta equals x.IDRuta
                             join per in db.Persona.ToList() on p.IDPersona.Value equals per.IDPersona
                             where p.IDPersona == CodigoPersonaCliente
                             select new HistorialViajeModel() { IDReserva = r.IDReserva, nombrePasajero = string.Format("{0} {1} {2}", p.Nombre, p.ApellidoPaterno, p.ApellidoMaterno), origen = x.Origen, destino = x.Destino, fechaViaje = r.FechaSalida.Value.ToShortDateString(), montoPasaje = (p.MontoPago == null)? 0 : p.MontoPago.Value, puntosAcumulados = ((per.PuntosAcumulados == null) ? 0 : per.PuntosAcumulados.Value).ToString(), puntosAGanar = x.PuntosAGanar.Value.ToString(), EstadoReserva = r.Estado }).ToList();
            model.historial = historial;
            return View(model);
        }


        public ActionResult Index(string Origen, string Destino, string TipoViaje, string FechaSalida, string FechaLlegada)
        {
            DateTime _FechaSalida = new DateTime(); 
            DateTime _FechaRegreso;
            try
            {
                _FechaSalida = DateTime.ParseExact(FechaSalida, "dd/MM/yyyy", null);
            }
            catch { return RedirectToAction("Index","INT_Principal"); };
            //catch { return RedirectToRoute("/"); }
            DateTime _FechaSalida_2 = _FechaSalida.AddDays(1);
            var model = new GenerateReservaModel();

            //var listaProgramacionFormateada = (from c in db.ProgramacionViaje select new { c.IDProgramacionViaje, FechaSalida = Convert.ToDateTime(c.FechaSalida.Value.ToString("dd/MM/yyyy")), FechaLlegada = Convert.ToDateTime(c.FechaLlegada.Value.ToString("dd/MM/yyyy")), c.Descripcion, CapacidadPasajeros = c.CapacidadPasajeros.Value, Precio = c.Precio.Value, c.IdRuta_x_UnidadTransporte, c.Estado, TipoServicio = c.TipoServicio.Value }).ToList();
            var listaProgramacionFormateada = db.ProgramacionViaje.Where(c => c.FechaSalida.Value >= _FechaSalida && c.FechaSalida.Value < _FechaSalida_2).ToList();

            //var listaProgramacionFormateada = db.ProgramacionViaje.Where(c => c.FechaSalida.Value >= _FechaSalida).ToList();

            var listaFiltrada = (from prog in listaProgramacionFormateada
                                 join ruta_unid in db.Ruta_x_UnidadTransporte on prog.IdRuta_x_UnidadTransporte equals ruta_unid.IdRuta_x_UnidadTransporte
                                 join ruta in db.Ruta on ruta_unid.IDRuta.Value equals ruta.IDRuta
                                 where ruta.Origen.Trim() == Origen && ruta.Destino.Trim() == Destino /*&& prog.FechaSalida == _FechaSalida*/ && ruta.Estado == "AC"
                                 select new ProgramacionDisponible { IdProgramcionViaje = prog.IDProgramacionViaje, Precio = prog.Precio.Value, DescriptionTipoServicio = (prog.TipoServicio == 1) ? "Economico" : "VIP", FechaSalida = prog.FechaSalida.Value, Origen = ruta.Origen, Destino = ruta.Destino }).ToList();

            if (!TipoViaje.Equals("IDA")) { 
            _FechaRegreso = Convert.ToDateTime(FechaLlegada);
            DateTime _FechaRegreso_2 = _FechaRegreso.AddDays(1);

            var listaProgramacionFormateadaVuelta = db.ProgramacionViaje.Where(c => c.FechaSalida.Value >= _FechaRegreso && c.FechaSalida.Value < _FechaRegreso_2).ToList();

            var listaFiltradaVuelta = (from prog in listaProgramacionFormateadaVuelta
                                 join ruta_unid in db.Ruta_x_UnidadTransporte on prog.IdRuta_x_UnidadTransporte equals ruta_unid.IdRuta_x_UnidadTransporte
                                 join ruta in db.Ruta on ruta_unid.IDRuta.Value equals ruta.IDRuta
                                 where ruta.Origen == Destino && ruta.Destino == Origen /*&& prog.FechaSalida.Value >= _FechaRegreso*/ && ruta.Estado == "AC"
                                 select new ProgramacionDisponible { IdProgramcionViaje = prog.IDProgramacionViaje, Precio = prog.Precio.Value, DescriptionTipoServicio = (prog.TipoServicio.Value == 1) ? "Economico" : "VIP", FechaSalida = prog.FechaSalida.Value, Origen = ruta.Origen, Destino = ruta.Destino }).ToList();
            model.listaProgramacionViajeVuelta = listaFiltradaVuelta.ToList<ProgramacionDisponible>();
            }
            model.TipoReserva = TipoViaje;
            model.listaProgramacionViaje = listaFiltrada.ToList<ProgramacionDisponible>(); 
            return View(model);
        }

        public JsonResult listarAsientosNoDisponibles(int idProgramacionViaje)
        {
            var datosProgramacion = db.ProgramacionViaje.ToList().Where(c => c.IDProgramacionViaje == idProgramacionViaje).First();
            var listaPasajes = (from c in db.Pasaje join r in db.Reserva on c.IDReserva equals r.IDReserva where c.IDProgramacionViaje == idProgramacionViaje && r.Estado == "AC" select new { c.NroAsiento }).ToList();
            var listaPasajesPago = (from c in db.Pasaje join r in db.Reserva on c.IDReserva equals r.IDReserva where c.IDProgramacionViaje == idProgramacionViaje && r.Estado == "CA" select new { c.NroAsiento }).ToList();
            return Json(new { listaAsientosReservados = listaPasajes, servicio = (datosProgramacion.TipoServicio.Value == 1) ? "Economico" : "VIP", precio = datosProgramacion.Precio, asientoPagado = listaPasajesPago });
        }

        public JsonResult listarAsientosNoDisponiblesVuelta(int idProgramacionViaje)
        {
            var datosProgramacion = db.ProgramacionViaje.ToList().Where(c => c.IDProgramacionViaje == idProgramacionViaje).First();
            var listaPasajes = (from c in db.Pasaje join r in db.Reserva on c.IDReserva equals r.IDReserva where c.IDProgramacionViaje == idProgramacionViaje && r.Estado == "AC" select new { c.NroAsiento }).ToList();
            var listaPasajesPago = (from c in db.Pasaje join r in db.Reserva on c.IDReserva equals r.IDReserva where c.IDProgramacionViaje == idProgramacionViaje && r.Estado == "CA" select new { c.NroAsiento }).ToList();
            return Json(new { listaAsientosReservados = listaPasajes, servicio = (datosProgramacion.TipoServicio.Value == 1) ? "Economico" : "VIP", precio = datosProgramacion.Precio, asientoPagado = listaPasajesPago });
        }

        public JsonResult getDatosPasajeroXDNI(string NroDni)
        {
            var datosPasajero = (from pe in db.Persona.ToList()
                                 where pe.DNI == NroDni
                                 select new { pe.Nombre, pe.ApellidoPaterno, pe.ApellidoMaterno, FechaNacimiento = pe.FechaNacimiento.Value.ToString("dd/MM/yyyy").ToString(), Telefono = pe.Telefono.Value, pe.Email, pe.Direccion }).ToList();
            if (datosPasajero.Any())
                return Json(new { any = 1, datos = datosPasajero.First() });
            else
                return Json(new { any = 0 });
        }

        public JsonResult agregarPasajeroTemporal(string nombrePasajero, string apPaternoPasajero, string apMaternoPasajero, string dniPasajero, string emailPasajero, string direccionPasajero, string fecNacimientoPasajero, string telefonoPasajero, int asiento, int asientoVuelta, string refrigerio, string almuerzo, string tipoDocumento)
        {
            List<PasajeroModel> listaPasajero;
            if (Session["PASAJEROS_REGISTRADOS_TEMP"] == null)
                listaPasajero = new List<PasajeroModel>();
            else
                listaPasajero = (List<PasajeroModel>)Session["PASAJEROS_REGISTRADOS_TEMP"];
            listaPasajero.Add(new PasajeroModel() { Nombre = nombrePasajero, ApellidoPaterno = apPaternoPasajero, ApellidoMaterno = apMaternoPasajero, DNI = dniPasajero, Email = emailPasajero, FechaNacimiento = fecNacimientoPasajero, Telefono = telefonoPasajero, FechaRegistro = DateTime.Now.ToShortDateString(), NroAsiento = asiento, NroAsientoVuelta = asientoVuelta, Refrigerio = refrigerio, Almuerzo = almuerzo, TipoDocumentos =  tipoDocumento });
            Session["PASAJEROS_REGISTRADOS_TEMP"] = listaPasajero;
            return Json(new { result = "1", mensajeRespuesta = "Se agrego al pasajero Satisfactoriamente" });
        }

        public JsonResult generarReserva(int idProgramacionViaje, int idProgramacionViajeVuelta)
        {
            using (TransactionScope oTransaction = new TransactionScope())
            {
                try
                {
                    var listadoPasajeros = (List<PasajeroModel>)Session["PASAJEROS_REGISTRADOS_TEMP"];
                    var datosProgramacion = db.ProgramacionViaje.ToList().Where(c => c.IDProgramacionViaje == idProgramacionViaje).First();
                    var reservaEntity = new Reserva();
                    var reservaEntityVuelta = new Reserva();
                    //reservaEntity.Origen = "LIMA";
                    //reservaEntity.Destino = "CUZCO";
                    reservaEntity.FechaSalida = datosProgramacion.FechaSalida.Value;
                    reservaEntity.FechaRetorno = datosProgramacion.FechaLlegada.Value;
                    reservaEntity.FechaLimite = DateTime.Now.AddDays(1);
                    reservaEntity.FechaRegistro = DateTime.Now;
                    reservaEntity.NumeroPasajeros = listadoPasajeros.Count();
                    reservaEntity.Estado = SystemField.ESTATE_REGISTER_ACTIVE;
                    db.Reserva.Add(reservaEntity);
                    db.SaveChanges();


                    if (idProgramacionViajeVuelta != 0) {
                        var datosProgramacionVuelta = db.ProgramacionViaje.ToList().Where(c => c.IDProgramacionViaje == idProgramacionViajeVuelta).First();    
                        reservaEntityVuelta.FechaSalida = datosProgramacionVuelta.FechaSalida.Value;
                        reservaEntityVuelta.FechaRetorno = datosProgramacionVuelta.FechaLlegada.Value;
                        reservaEntityVuelta.FechaLimite = DateTime.Now.AddDays(2);
                        reservaEntityVuelta.FechaRegistro = DateTime.Now;
                        reservaEntityVuelta.NumeroPasajeros = listadoPasajeros.Count();
                        reservaEntityVuelta.Estado = SystemField.ESTATE_REGISTER_ACTIVE;
                        reservaEntityVuelta.IdAnexo = reservaEntity.IDReserva;
                        db.Reserva.Add(reservaEntityVuelta);
                        db.SaveChanges();
                    }


                    bool getFirstPasajero = false;
                    int idPersonaRegistradaPrimeraFila = 0;
                    foreach (var item in listadoPasajeros)
                    {
                        var pasajeVueltaOcupada = (from c in db.Pasaje join r in db.Reserva on c.IDReserva equals r.IDReserva where c.IDProgramacionViaje == idProgramacionViaje && r.Estado != "AN" && c.NroAsiento.Value == item.NroAsiento select new { Asiento = c.NroAsiento }).ToList(); //(from c in db.Pasaje.ToList() where c.NroAsiento == item.NroAsiento && c.IDProgramacionViaje == idProgramacionViaje select c).ToList();
                        if (pasajeVueltaOcupada.Any()) {
                            Session["PASAJEROS_REGISTRADOS_TEMP"] = null;
                            throw new Exception("Uno de los asientos seleccionados (Viaje ida) ya se encuentra ocupado. Su reserva no se puede generar");
                        }

                        if (idProgramacionViajeVuelta != 0)
                        {
                            var pasajeVueltaOcupadaVuelta = (from c in db.Pasaje join r in db.Reserva on c.IDReserva equals r.IDReserva where c.IDProgramacionViaje == idProgramacionViajeVuelta && r.Estado != "AN" && c.NroAsiento.Value == item.NroAsientoVuelta select new { Asiento = c.NroAsiento }).ToList();//(from c in db.Pasaje.ToList() where c.NroAsiento == item.NroAsientoVuelta && c.IDProgramacionViaje == idProgramacionViajeVuelta select c).ToList();
                            if (pasajeVueltaOcupadaVuelta.Any()) {
                                Session["PASAJEROS_REGISTRADOS_TEMP"] = null;
                                throw new Exception("Uno de los asientos seleccionados (Viaje retorno) ya se encuentra ocupado. Su reserva no se puede generar");
                            }                            
                        }


                        var personaEntity = new Persona();
                        var validaExistePersonaTable = (from c in db.Persona.ToList() where c.DNI == item.DNI select c);
                        if (validaExistePersonaTable.Any()) {
                            personaEntity.IDPersona = validaExistePersonaTable.First().IDPersona;   
                        } else {
                            personaEntity.DNI = item.DNI;
                            personaEntity.Nombre = item.Nombre;
                            personaEntity.ApellidoPaterno = item.ApellidoPaterno;
                            personaEntity.ApellidoMaterno = item.ApellidoMaterno;
                            personaEntity.Direccion = "";
                            personaEntity.Email = item.Email;
                            personaEntity.Telefono = Convert.ToInt32(item.Telefono);
                            personaEntity.FechaNacimiento = Convert.ToDateTime(item.FechaNacimiento);
                            personaEntity.Estado = SystemField.ESTATE_REGISTER_ACTIVE;
                            personaEntity.TipoPersona = SystemField.ID_PERSONA_PASAJERO_COMUN;
                            personaEntity.PuntosAcumulados = 0;
                            personaEntity.tipoDocumento = item.TipoDocumentos;

                            

                            db.Persona.Add(personaEntity);
                            db.SaveChanges();

                            db.Usuario.Add(new Usuario() { Nombre = item.DNI, Contraseña = SetHash("123"), IDPersona = personaEntity.IDPersona, IDPerfil = SystemField.ID_USUARIO_PERSONA_COMUN });
                            db.SaveChanges();
                        }

                        if (!getFirstPasajero)
                        {
                            idPersonaRegistradaPrimeraFila = personaEntity.IDPersona;
                            getFirstPasajero = true;
                        }

                        var pasajeEntity = new Pasaje();
                        pasajeEntity.Nombre = item.Nombre;
                        pasajeEntity.ApellidoPaterno = item.ApellidoPaterno;
                        pasajeEntity.ApellidoMaterno = item.ApellidoMaterno;
                        pasajeEntity.DNI = "";
                        pasajeEntity.NroAsiento = item.NroAsiento;
                        pasajeEntity.Estado = SystemField.ESTATE_REGISTER_ACTIVE;
                        pasajeEntity.IDProgramacionViaje = idProgramacionViaje;
                        pasajeEntity.IDPersona = personaEntity.IDPersona;
                        pasajeEntity.IDReserva = reservaEntity.IDReserva;
                        pasajeEntity.MontoCosto = 0;
                        pasajeEntity.MontoDescuento = 0;
                        pasajeEntity.MontoPago = 0;
                        pasajeEntity.Almuerzo = item.Almuerzo;
                        pasajeEntity.Refrigerio = item.Refrigerio;
                        db.Pasaje.Add(pasajeEntity);
                        db.SaveChanges();

                        if (idProgramacionViajeVuelta != 0)
                        {
                            var pasajeEntityVuelta = new Pasaje();
                            pasajeEntityVuelta.Nombre = item.Nombre;
                            pasajeEntityVuelta.ApellidoPaterno = item.ApellidoPaterno;
                            pasajeEntityVuelta.ApellidoMaterno = item.ApellidoMaterno;
                            pasajeEntityVuelta.DNI = "";
                            pasajeEntityVuelta.NroAsiento = item.NroAsientoVuelta;
                            pasajeEntityVuelta.Estado = SystemField.ESTATE_REGISTER_ACTIVE;
                            pasajeEntityVuelta.IDProgramacionViaje = idProgramacionViajeVuelta;
                            pasajeEntityVuelta.IDPersona = personaEntity.IDPersona;
                            pasajeEntityVuelta.IDReserva = reservaEntityVuelta.IDReserva;
                            pasajeEntityVuelta.MontoCosto = 0;
                            pasajeEntityVuelta.MontoDescuento = 0;
                            pasajeEntityVuelta.MontoPago = 0;
                            pasajeEntityVuelta.Almuerzo = item.Almuerzo;
                            pasajeEntityVuelta.Refrigerio = item.Refrigerio;
                            db.Pasaje.Add(pasajeEntityVuelta);
                            db.SaveChanges();
                        }
                    }

                    var reserva = db.Reserva.ToList().Where(c => c.IDReserva == reservaEntity.IDReserva).First();
                    reserva.IDPersona = idPersonaRegistradaPrimeraFila;
                    if (idProgramacionViajeVuelta != 0) {
                        var reservaVuelta = db.Reserva.ToList().Where(c => c.IDReserva == reservaEntityVuelta.IDReserva).First();
                        reservaVuelta.IDPersona = idPersonaRegistradaPrimeraFila;
                    }
                    db.SaveChanges();

                    Session["PASAJEROS_REGISTRADOS_TEMP"] = null;
                    oTransaction.Complete();
                    return Json(new { result = "1", mensajeRespuesta = "Se genero su reserva satisfactoriamente el numero de Reserva es : " + reservaEntity.IDReserva });
                }
                catch (Exception ex)
                {
                    oTransaction.Dispose();
                    return Json(new { result = "0", mensajeRespuesta = ex.Message.ToString() });
                }
            }
        }

        private static string SetHash(string a)
        {
            using (MD5 md5Hash = MD5.Create())
            {
                return GetMd5Hash(md5Hash, a);
            }
        }


        public static string GetMd5Hash(MD5 md5Hash, string input)
        {
            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();
            // Loop through each byte of the hashed data 
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            // Return the hexadecimal string.
            return sBuilder.ToString();
        }


	}
}